package com.diyphonegadgets.yandroidcontroller;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.diyphonegadgets.yandroidcontroller.joystick.DualJoystickView;
import com.diyphonegadgets.yandroidcontroller.joystick.JoystickMovedListener;
import com.diyphonegadgets.yandroidcontroller.wifi.CommandListener;
import com.diyphonegadgets.yandroidcontroller.wifi.CommandManager;
import com.diyphonegadgets.yandroidcontroller.wifi.GlobalData;

public class YandroidControllerActivity extends Activity implements CommandListener {

	private SharedPreferences preferences;

	private int leftX, leftY, rightX, rightY = 0;
	String incomingData = "";

	private DualJoystickView joystick;
	
	private LinearLayout mainView;
	Bitmap bmp;
	int port =8123;
	ServerSocket serverSocket;

	InputStream inputStream;
	final String TAG = "downStream [DownStream]";
	boolean exception=false;
	DownStreamer ds;
	Thread streamerThread;
	boolean connected = false;
	Socket client;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);

		mainView=(LinearLayout) findViewById(R.id.main_view);
		joystick = (DualJoystickView) findViewById(R.id.dualjoystickView);
		joystick.setOnJostickMovedListener(_listenerLeft, _listenerRight);

		// Initialize preferences
		preferences = PreferenceManager.getDefaultSharedPreferences(this);
		CommandManager.init();
		CommandManager.startListening(this);
		

		ds=new DownStreamer(port);
		streamerThread=new Thread(ds);
		streamerThread.start();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		startActivity(new Intent(this, Preferences.class));
		return true;
	}

	private JoystickMovedListener _listenerLeft = new JoystickMovedListener() {

		@Override
		public void OnMoved(int pan, int tilt) {
			leftX = pan;
			leftY = tilt;
			GlobalData.leftActive = true;

			GlobalData.leftX = leftX * 200 / 150;
			GlobalData.leftY = leftY * 200 / 150;

			Log.d("LEFT=", "" + GlobalData.leftY);

		}

		@Override
		public void OnReleased() {
			GlobalData.leftX = 0;
			GlobalData.leftY = 0;

			/*Thread t = new Thread() {
				public void run() {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					GlobalData.leftActive = false;

				}
			};
			t.start();*/
		}

		public void OnReturnedToCenter() {
			GlobalData.leftX = 0;
			GlobalData.leftY = 0;

			/*Thread t = new Thread() {
				public void run() {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					GlobalData.leftActive = false;

				}
			};
			t.start();*/
		};
	};

	private JoystickMovedListener _listenerRight = new JoystickMovedListener() {

		@Override
		public void OnMoved(int pan, int tilt) {
			rightX = pan;
			rightY = tilt;
			GlobalData.rightActive = true;

			GlobalData.rightX = rightX * 200 / 150;
			GlobalData.rightY = rightY * 200 / 150;

			Log.d("RIGHT=", "" + GlobalData.rightY);

		}

		@Override
		public void OnReleased() {
			GlobalData.rightX = 0;
			GlobalData.rightY = 0;
/*
			Thread t = new Thread() {
				public void run() {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					GlobalData.rightActive = false;

				}
			};
			t.start();*/
		}

		public void OnReturnedToCenter() {
			GlobalData.rightX = 0;
			GlobalData.rightY = 0;

		/*	Thread t = new Thread() {
				public void run() {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					GlobalData.rightActive = false;

				}
			};
			t.start();*/
		};
	};

	@Override
	protected void onPause() {

		super.onPause();
	}

	@Override
	protected void onResume() {
		super.onResume();

	}

	@Override
	public void onCommandChanged(JSONObject data) {

		try {
			incomingData = data.getString("ServoValueLeft");
			// directionText.setText(incomingData);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	final Handler messageHandler = new Handler() 
	{

		@Override
		public void handleMessage(Message msg) 
		{  
			mainView.setBackgroundDrawable(new BitmapDrawable(bmp));
        }
	};
    
 public void resetConnection(){
	 
		try
		{
			serverSocket.close();
			client.close();
			inputStream.close();
			
			serverSocket=null;
			client=null;
			
			ds=null;
			streamerThread=null;
			
			Thread.sleep(500);

		}
		catch(Exception ex)
		{
		}
	 
		
		
		ds=new DownStreamer(port);
		streamerThread=new Thread(ds);
		streamerThread.start();
	 
 }
 
 
 


	/*void disconnect(){
		try {
			dos.flush();
			dos.close();
			s.close();
			connected=false;
			connectButton.setImageResource(R.drawable.connectbuttonstates);
		} catch (Exception e) {}
 }*/
 

  
    public static byte[] readBytes(Socket socket, int aMaxBytes) throws IOException {
   
		Log.i("","1111");

		
		InputStream in=new FlushedInputStream (socket.getInputStream());
    	
		  byte[] input = new byte[aMaxBytes];
		    for (int i = 0; i < input.length; i++) {
		      int b = in.read( );

		      if (b  == -1) 
		       break;
		      input[i] = (byte) b;
		    }
			return input;
    	}
    
    
    
    
  
    
    class DownStreamer implements Runnable
	{
	
		
		public DownStreamer(int p)
		{
			p=port;
		}
		
		@Override
		public void run()
		{
			
	
			/*client = new Socket();
			try {
				client.connect(new InetSocketAddress("192.168.43.1", 8123), 3000);

				connected=true;
			} catch (IOException e) {
				e.printStackTrace();
			}	
			
			
				while(true && !exception)
				{
					
					
				try
				{   
					
					
					
					Log.i(TAG,"Connected.\nObtaining input stream...");
					
					
					try {
						inputStream=client.getInputStream();
					} catch (IOException e) {
						exception=true;
						e.printStackTrace();
						resetConnection();

					}


					Bitmap	newBmp = null;
					
                    if(inputStream!=null)
                    	
                    	try{
					newBmp = BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
                    	}
                    
                    catch (Exception e) {
						exception=true;
						e.printStackTrace();
						resetConnection();

					}



					
					if(newBmp != null)
					{
						bmp=newBmp;
						messageHandler.sendEmptyMessage(0);
						Log.i(TAG,"Done.");

					}

				
					
				}
				catch(Exception ex)
				{
					Log.e(TAG,"Exception in reading...\n" + ex.toString()); 
					exception=true;
					resetConnection();

				}
			
			}
			
				resetConnection();*/
			
			
			
			
			
		         Socket    client    = new Socket();
		         
				try {
					client.connect(new InetSocketAddress("192.168.43.1", 8123), 3000);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

		       
		         while (true&& !exception) 
		         {
		        	 
						try
						{   
							
							/*
						     line = console.readLine();
					            if (line.equalsIgnoreCase(".bye"))
					               done = true;
					            socketOut.writeBytes(line + '\n');
					            */
					            
					            
							Log.i(TAG,"Connected.\nObtaining input stream...");
							
							   //DataOutputStream dataOutputStream = new DataOutputStream(client.getOutputStream());
						       InputStream  inputStream  = client.getInputStream();
						      // DataInputStream  console   = new DataInputStream(System.in);
											
					


							Bitmap	newBmp = null;
							
		                    if(inputStream!=null)
		                    	
		                    	try{
							newBmp = BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
		                    	}
		                    
		                    catch (Exception e) {
								exception=true;
								e.printStackTrace();
								resetConnection();

							}



							
							if(newBmp != null)
							{
								bmp=newBmp;
								messageHandler.sendEmptyMessage(0);
								Log.i(TAG,"Done.");

							}

						
							
						}
						catch(Exception ex)
						{
							Log.e(TAG,"Exception in reading...\n" + ex.toString()); 
							exception=true;
							resetConnection();

						}
		       
		         }
		         resetConnection();  
		}
		
			
			
	}	
    
    
    
    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        @Override
        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L) {
                    int b = read();
                    if (b < 0) {
                        break;  // we reached EOF
                    } else {
                        bytesSkipped = 1; // we read one byte
                    }
                }
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }
}